package com.kayb.patterns.behavioral;

/**
 * 备忘录模式，在不违反封装的情况下获得对象的内部状态，从而在需要时可以将对象恢复到最初状态。
 * 场景：undolog/redolog
 * @author huangkaibin
 * @date 2018-08-29
 **/
public class Memento {

    // 需要保留的状态
    interface StateKeeper {
        String getName();
        int getMoney();
    }

    // 具体操作类
    interface Service extends StateKeeper {
        StateKeeper backup();
        void restore(StateKeeper stateKeeper);
    }

    static class ServiceImpl implements Service {

        private String name;
        private int money;

        public ServiceImpl(String name, int money) {
            this.name = name;
            this.money = money;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public int getMoney() {
            return money;
        }

        public void incrMoney(int money) {
            this.money += money;
        }

        @Override
        public StateKeeper backup() {
            final String n = this.name;
            final int m = this.money;
            return new StateKeeper() {
                @Override
                public String getName() {
                    return n;
                }
                @Override
                public int getMoney() {
                    return m;
                }
            };
        }

        @Override
        public void restore(StateKeeper stateKeeper) {
            this.name = stateKeeper.getName();
            this.money = stateKeeper.getMoney();
        }
    }

    public static void main(String[] args) {
        ServiceImpl service = null;
        StateKeeper stateKeeper = null;
        try {
            service = new ServiceImpl("Alex", 9999999);
            System.out.println(service.getName() + ":" + service.getMoney());
            stateKeeper = service.backup();

            // do something
            service.incrMoney(1);
            System.out.println(service.getName() + ":" + service.getMoney());
            // throw exception
            throw new RuntimeException();
        } catch (Exception e) {
            // restore
            if (service != null && stateKeeper != null) {
                service.restore(stateKeeper);
                System.out.println(service.getName() + ":" + service.getMoney());
            }
        }
    }

}
